package p.ithorns.sample.refresh;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ValueRefreshService
 *
 * @author HtL
 * @date 2025/3/14 15:09
 * @since 1.0.0
 */
@Slf4j
@Component
public class ValueRefreshService {

    /**
     * SpEL表达式解析器
     */
    private final ExpressionParser parser = new SpelExpressionParser();
    /**
     * 模版解析上下文
     */
    private final TemplateParserContext parserContext = new TemplateParserContext();

    private final ApplicationContext appCtx;

    private final Binder binder;
    private final PropertySourcesPropertyResolver propertyResolver;


    public ValueRefreshService(ApplicationContext appCtx,
                               ConfigurableEnvironment env) {
        this.appCtx = appCtx;
        this.binder = Binder.get(env);
        this.propertyResolver = new PropertySourcesPropertyResolver(env.getPropertySources());
    }

    /**
     * 刷新@Value
     */

    @EventListener
    public void refreshValue(ConfigChangeListener.RefreshEvent event) {
        System.out.println("=============> 刷新Value ");
        Map<String, Object> params = event.getParams();
        Set<Map.Entry<String, Object>> entries = params.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            String key = entry.getKey();
            ValueHolder vh = ConfigContext.getValueHolder(key);
            if (null == vh) {
                continue;
            }

            Consumer<Binder> updater = vh.getUpdater();
            // 使用Binder就不用自己解value了
            // 解析占位符
            // String placeholder = vh.getPlaceholder();
            // String resolved = propertyResolver.resolveRequiredPlaceholders(placeholder);
            // EL表达式解析 兼容形如：@Value("#{'${app.user.value:nnn}'.toUpperCase()}")含有EL表达式的情况
            // Object newValue = parser.parseExpression(resolved, parserContext).getValue(vh.getTargetType());
            updater.accept(binder);
        }
    }

}